package com.yuzhi.master.conBjMx.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuzhi.common.contant.Constants;
import com.yuzhi.common.core.page.PageDataInfo;
import com.yuzhi.common.util.StringUtils;
import com.yuzhi.master.conBjMx.domain.ConBjMx;
import com.yuzhi.master.conBjMx.domain.bo.ConBjMxBo;
import com.yuzhi.master.conBjMx.domain.request.AlarmDashboardReq;
import com.yuzhi.master.conBjMx.domain.request.ConBjMxReq;
import com.yuzhi.master.conBjMx.domain.vo.AlarmEventListVo;
import com.yuzhi.master.conBjMx.domain.vo.AlarmStatisticsVo;
import com.yuzhi.master.conBjMx.domain.vo.AlarmTrendVo;
import com.yuzhi.master.conBjMx.domain.vo.ConBjMxVo;
import com.yuzhi.master.conBjMx.mapper.ConBjMxMapper;
import com.yuzhi.master.conBjMx.service.IConBjMxService;
import com.yuzhi.master.drainAlarmRule.domain.vo.DrainAlarmRuleVo;
import com.yuzhi.master.drainAlarmRule.mapper.DrainAlarmRuleMapper;
import com.yuzhi.master.drainEvents.domain.bo.DrainEvents;
import com.yuzhi.master.drainEvents.mapper.DrainEventsMapper;
import com.yuzhi.system.mapper.SysUserDeptMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 报警异常明细表Service业务层处理
 *
 * @author auto code generator
 * @date 2025-07-17
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ConBjMxServiceImpl implements IConBjMxService {

    @Autowired
    private ConBjMxMapper baseMapper;
    private final DrainEventsMapper drainEventsMapper;
    private final DrainAlarmRuleMapper drainAlarmRuleMapper;
    private final SysUserDeptMapper userDeptMapper;

    /**
     * 告警转工单
     *
     * @param conBjMxBo 告警记录
     * @param ruleVo    告警规则
     * @return
     */
    @Override
    public Boolean conBjTransferWork(ConBjMxBo conBjMxBo, DrainAlarmRuleVo ruleVo) {
        //1、新增告警记录
        boolean flag = this.insertByBo(conBjMxBo);

        //告警记录转工单信息
        if (ruleVo.getTransferWork())  //是-需要转工单
        {
            DrainEvents events = changeEventInfo(conBjMxBo, ruleVo);
            drainEventsMapper.insert(events);

        }

        return flag;

    }

    /**
     * 告警信息转工单信息
     * @return
     */
    private DrainEvents changeEventInfo(ConBjMxBo conBjMx, DrainAlarmRuleVo ruleVo) {
        DrainEvents events = new DrainEvents();
        //事件来源
        events.setSourceType("4");
        //events.setSource(conBjMx.getFKeyName());
        //事件来源ID
        events.setSourceId(conBjMx.getId());
        if (conBjMx.getFKeyType() != null) {
            String siteType = conBjMx.getFKeyType() + "";
            if (conBjMx.getFKeyType() == 5)  // 排口
            {
                siteType = "3"; //1、污水厂   2：泵站 3：排口  4：管网
            }
            if (conBjMx.getFKeyType() == 3 || conBjMx.getFKeyType() == 4
                    || conBjMx.getFKeyType() == 6 || conBjMx.getFKeyType() == 7) {
                siteType = "4";   //1、污水厂   2：泵站 3：排口  4：污水管网
            }
            events.setSiteType(siteType);
        }
        events.setSiteName(conBjMx.getFKey());  //排水设施编码
        // 工单描述
        events.setDescription(conBjMx.getCbDesc());
        //工单上报
        events.setStatusType(2);

        //告警规则
        String alarmRuleId = conBjMx.getAlarmRuleId();
        if (StringUtils.isNotBlank(alarmRuleId)) {
            // 工单接收人
            String handlerPerson = ruleVo.getHandlerPerson();
            if (StringUtils.isNotBlank(handlerPerson)) {
                //用户对应的部门
                List<String> deptList = userDeptMapper.selectdeptIdsByUserId(handlerPerson);
                events.setReporterId(handlerPerson);
                events.setAdmacd(deptList.get(0));//用户部门
            }

        }
        //工单状态(1(待处理)、2(处理中)、3(已解决)、4(已关闭)、5(催办))
        events.setEventsStatus("1");
        return events;
    }

    /**
     * 查询报警异常明细表
     */
    @Override
    public ConBjMxVo queryById(String id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询报警异常明细表列表
     */
    @Override
    public PageDataInfo<ConBjMxVo> queryPageList(ConBjMxReq request) {
        LambdaQueryWrapper<ConBjMx> lqw = buildQueryWrapper(request);
        Page<ConBjMxVo> result = baseMapper.selectVoPage(request.getPageQuery().build(), lqw);
        return PageDataInfo.build(result);
    }

    /**
     * 查询报警异常明细表列表
     */
    @Override
    public List<ConBjMxVo> queryList(ConBjMxReq request) {
        LambdaQueryWrapper<ConBjMx> lqw = buildQueryWrapper(request);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ConBjMx> buildQueryWrapper(ConBjMxReq request) {
        Map<String, Object> params = request.getParams();
        LambdaQueryWrapper<ConBjMx> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(request.getFKey()), ConBjMx::getFKey, request.getFKey());
        lqw.eq(request.getFKeyType() != null, ConBjMx::getFKeyType, request.getFKeyType());
        lqw.eq(StringUtils.isNotBlank(request.getBjType()), ConBjMx::getBjType, request.getBjType());
        lqw.like(StringUtils.isNotBlank(request.getFKeyName()), ConBjMx::getFKeyName, request.getFKeyName());
        if (request.getIsClList() != null && !request.getIsClList().isEmpty()) {
            lqw.in(ConBjMx::getIsCl, request.getIsClList());
        }
        if (request.getQueryStartTime() != null && request.getQueryEndTime() != null) {
            LocalDateTime startTime = request.getQueryStartTime().toLocalDate().atStartOfDay();
            LocalDateTime endTime = request.getQueryEndTime().toLocalDate().atTime(LocalTime.MAX);
            lqw.between(ConBjMx::getCbTime, startTime, endTime);
        }
        lqw.orderByDesc(ConBjMx::getCbTime);
        return lqw;
    }

    /**
     * 新增报警异常明细表
     */
    @Override
    public Boolean insertByBo(ConBjMxBo bo) {
        ConBjMx add = BeanUtil.toBean(bo, ConBjMx.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改报警异常明细表
     */
    @Override
    public Boolean updateByBo(ConBjMxBo bo) {
        ConBjMx update = BeanUtil.toBean(bo, ConBjMx.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ConBjMx entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除报警异常明细表
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public List<ConBjMxVo> getTodayRecordsByKeyType(Integer keyType) {
        return baseMapper.selectTodayRecordsByKeyType(keyType);
    }

    @Override
    public Map<String, Integer> getTodayStatistics() {
        return baseMapper.getTodayStatistics();
    }

    @Override
    public List<ConBjMxVo> getfFeyId(ConBjMxBo bo) {
        LambdaQueryWrapper<ConBjMx> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getFKey()), ConBjMx::getFKey, bo.getFKey());
        lqw.eq(ConBjMx::getBjType, bo.getBjType());
        lqw.orderByDesc(ConBjMx::getCbTime).last("limit 1");
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 根据id删除报警异常明细表信息
     */
    @Override
    public Boolean deleteById(String id, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteById(id) > 0;
    }

    /**
     * 设备在线更新异常告警结束时间和处置状态
     *
     * @param fkId
     * @return
     */
    @Override
    public Boolean updateOnlineConBjMx(String fkId) {
        //0：待受理，1：需处理，2：处理中，3：已处理，4：无需处理
        List<String> statusList = new ArrayList<>();
        statusList.add("0");
        statusList.add("1");
        statusList.add("2");

        LambdaUpdateWrapper<ConBjMx> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
                .eq(ConBjMx::getFKey, fkId)
                .eq(ConBjMx::getBjType, "1")
                .in(ConBjMx::getIsCl, statusList)
                // 设置要更新的字段和值
                .set(ConBjMx::getCbEndTime, LocalDateTime.now())
                .set(ConBjMx::getIsCl, "3");  //已处理

        return baseMapper.update(updateWrapper) > 0;
    }

    /**
     * 根据fKey更新最新一条记录的报警结束时间和处理状态
     *
     * @param fKey      外键ID
     * @param cbEndTime 报警结束时间
     * @param isCl      处理状态
     * @return 更新结果
     */
    @Override
    public Boolean updateLatestRecordByFKey(String fKey, String bjType, LocalDateTime cbEndTime, String isCl) {
        // 1. 根据fKey查询最新的一条记录
        LambdaQueryWrapper<ConBjMx> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ConBjMx::getFKey, fKey)
                .eq(ConBjMx::getBjType, bjType)
                .in(ConBjMx::getIsCl, "0", "1", "2")
                .eq(ConBjMx::getDeleted, 0)
                .orderByDesc(ConBjMx::getCbTime)
                .last("limit 1");
        ConBjMx latestRecord = baseMapper.selectOne(queryWrapper);
        if (latestRecord == null) {
            log.warn("未找到fKey为{}的记录", fKey);
            return false;
        }
        // 2. 更新该记录的cbEndTime和isCl字段
        LambdaUpdateWrapper<ConBjMx> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(ConBjMx::getId, latestRecord.getId());
        // 如果传入了cbEndTime，则更新
        if (cbEndTime != null) {
            updateWrapper.set(ConBjMx::getCbEndTime, cbEndTime);
        }
        // 如果传入了isCl，则更新
        if (StringUtils.isNotBlank(isCl)) {
            updateWrapper.set(ConBjMx::getIsCl, isCl);
        }

        boolean result = baseMapper.update(updateWrapper) > 0;

        if (result) {
            log.info("成功更新fKey为{}的最新记录，记录ID：{}", fKey, latestRecord.getId());
        } else {
            log.warn("更新fKey为{}的最新记录失败", fKey);
        }

        return result;
    }


    /**
     * 更新异常告警处置状态
     *
     * @param ids
     * @param isValid
     * @return
     */
    @Override
    public Boolean updateIsClByIds(Collection<String> ids, Boolean isValid) {
        LambdaUpdateWrapper<ConBjMx> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
                .in(ConBjMx::getId, ids)
                // 设置要更新的字段和值
                .set(ConBjMx::getCbEndTime, LocalDateTime.now())
                .set(ConBjMx::getIsCl, "3");  //已处理

        return baseMapper.update(updateWrapper) > 0;
    }





    /**
     * 告警处理
     *
     * @param request
     * @return
     */
    @Override
    public PageDataInfo alarmEventHandling(ConBjMxReq request) {
        LambdaQueryWrapper<ConBjMx> lqw = buildQueryWrapper2(request);
        // 构建分页对象并查询
        Page<ConBjMxVo> result = baseMapper.selectVoPage(request.getPageQuery().build(), lqw);
        return PageDataInfo.build(result);
    }

    private LambdaQueryWrapper<ConBjMx> buildQueryWrapper2(ConBjMxReq request) {
        LambdaQueryWrapper<ConBjMx> lqw = Wrappers.lambdaQuery();
        // 1. 逻辑删除条件（deleted = 0）
        lqw.eq(ConBjMx::getDeleted, Constants.UNDELETED);
        // 0待处理 1需处理
        lqw.in(ConBjMx::getIsCl, "0", "1");
        // 1污水厂 2泵站
        lqw.in(ConBjMx::getFKeyType, "1", "2");
        // 2. 当天时间范围条件（cb_time >= 当天0点 AND cb_time < 次日0点）
        // 获取当天0点0分0秒
        LocalDateTime todayStart = LocalDate.now().atStartOfDay();
        // 次日0点0分0秒（不含）
        LocalDateTime tomorrowStart = todayStart.plusDays(1);
        // 添加时间范围条件（精准匹配当天数据）
        lqw.ge(ConBjMx::getCbTime, todayStart)// >= 当天0点
                .lt(ConBjMx::getCbTime, tomorrowStart);// < 次日0点
        return lqw;
    }

    @Override
    public List<String> getAlarmDeviceStats() {
        return baseMapper.getAlarmDeviceStats();
    }

    /**
     * 获取报警统计信息（四个统计卡片数据）
     */
    @Override
    public AlarmStatisticsVo getAlarmStatistics(AlarmDashboardReq request) {
        return baseMapper.getAlarmStatistics(buildQueryConditions(request));
    }

    /**
     * 获取报警趋势数据（近7天趋势图表）
     */
    @Override
    public AlarmTrendVo getAlarmTrend(AlarmDashboardReq request) {
        List<AlarmTrendVo.AlarmTrendDataVo> trendData = baseMapper.getAlarmTrend(buildQueryConditions(request));
        AlarmTrendVo trendVo = new AlarmTrendVo();
        trendVo.setTrendData(trendData);
        return trendVo;
    }

    /**
     * 获取报警事件列表
     */
    @Override
    public AlarmEventListVo getAlarmEventList(AlarmDashboardReq request) {
        // 构建查询条件
        Map<String, Object> queryConditions = buildQueryConditions(request);

        // 获取事件列表
        List<AlarmEventListVo.AlarmEventVo> alarmEvents = baseMapper.getAlarmEventList(queryConditions);

        // 获取总数
        Long total = baseMapper.getAlarmEventListCount(queryConditions);

        AlarmEventListVo eventListVo = new AlarmEventListVo();
        eventListVo.setAlarmEvents(alarmEvents);
        eventListVo.setTotal(total);

        return eventListVo;
    }

    /**
     * 构建查询条件
     */
    private Map<String, Object> buildQueryConditions(AlarmDashboardReq request) {
        Map<String, Object> conditions = new java.util.HashMap<>();

        // 时间范围处理
        if (StringUtils.isNotBlank(request.getTimeRange())) {
            LocalDateTime startTime = null;
            LocalDateTime endTime = null;

            switch (request.getTimeRange()) {
                case "today":
                    startTime = LocalDateTime.now().toLocalDate().atStartOfDay();
                    endTime = LocalDateTime.now().toLocalDate().atTime(LocalTime.MAX);
                    break;
                case "last7days":
                    startTime = LocalDateTime.now().minusDays(7).toLocalDate().atStartOfDay();
                    endTime = LocalDateTime.now().toLocalDate().atTime(LocalTime.MAX);
                    break;
                case "last30days":
                    startTime = LocalDateTime.now().minusDays(30).toLocalDate().atStartOfDay();
                    endTime = LocalDateTime.now().toLocalDate().atTime(LocalTime.MAX);
                    break;
                case "custom":
                    if (StringUtils.isNotBlank(request.getStartDate()) && StringUtils.isNotBlank(request.getEndDate())) {
                        startTime = LocalDateTime.parse(request.getStartDate() + " 00:00:00",
                            java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                        endTime = LocalDateTime.parse(request.getEndDate() + " 23:59:59",
                            java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    }
                    break;
            }

            if (startTime != null && endTime != null) {
                conditions.put("startTime", startTime);
                conditions.put("endTime", endTime);
            }
        }

        // 区域筛选
        if (StringUtils.isNotBlank(request.getRegion()) && !"all".equals(request.getRegion())) {
            conditions.put("region", request.getRegion());
        }

        // 报警类型筛选
        if (StringUtils.isNotBlank(request.getAlarmType()) && !"all".equals(request.getAlarmType())) {
            conditions.put("alarmType", request.getAlarmType());
        }

        return conditions;
    }


}
